package NetWork;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;

/**
 * Created with IntelliJ IDEA.
 * Description:UDP服务器
 * User:Lenovo
 * Date:2022-04-09
 * Time:14:48
 */
//站在服务器的角度：
//源IP：服务器程序本身的IP
//源端口：服务器绑定的端口（此处手动制定了9090）
//目的IP:包含在收到的数据报中，（客户端的IP）
//目的端口：包含在收到的数据报中，（客户端的端口）
//协议类型：UDP
public class UdpEchoServer {
    //进行网络编程，第一步就需要先准备好socket实例~这是进行网络编程的大前提.
    private DatagramSocket socket = null;
    //此处在构造服务器这边的socket对象的时候，就需要显式的绑定一个端口号，运行程序时指定即可
    public  UdpEchoServer(int port) throws SocketException {//构造socket对象有很多失败的可能
        socket = new DatagramSocket(port);
        //端口号是用来区分一个应用程序的~~主机收到网卡上的数据的时候，这个数据该给哪个程序？
    }
    //启动服务器
    public void start() throws IOException {
        System.out.println("启动服务器!");
        //UDP不需要建立连接，直接接收从客户端来的数据即可~
        while (true){
            //1.读取客户端发来的请求
            //  1.1为了接收数据，需要先准备好一个空的DatagramPacket对象，由receive来进行填充数据
            DatagramPacket requestPacket = new DatagramPacket(new byte[1024],1024);//把字节数组包装了一下
            socket.receive(requestPacket);//receive对这个参数进行填充，“输出型参数”
            //把DatagramPacket解析成一个String
            String request = new String(requestPacket.getData(),0,requestPacket.getLength(),"UTF-8");
            //2.根据请求计算响应（回显服务，2省略）
            String response = process(request);
            //3.把响应写回客户端
            //  3.1：send方法的参数，也是DatagramPacket，需要把响应数据先构造成一个DatagramPacket再进行发送
            //  3.2:这里就不是构造一个空的DatagramPacket了，而是有数据的
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes(StandardCharsets.UTF_8),response.getBytes().length,requestPacket.getSocketAddress());
            System.out.printf("[%s:%d] req: %s, resp: %s\n",requestPacket.getAddress().toString(),requestPacket.getPort(),request,response);
            //  3.3:在DatagramPacket构造方法中，指定了第三个参数，表示要把数据发送给哪个地址+端口
            socket.send(responsePacket);
        }
    }
    //由于是回显服务，响应和请求就是一样的了
    //实际上对于一个真实的服务器来说，这个过程是最复杂的，为了实现这个过程，可能需要n万行代码.....
    public String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpEchoServer server = new UdpEchoServer(9090);
        server.start();
    }
}
